package cn.hqc.basic.service.impl;


import cn.hqc.basic.cons.PhoneRegisterCons;
import cn.hqc.basic.dto.SmsCodeDto;
import cn.hqc.basic.service.VerifyCodeService;
import cn.hqc.basic.utils.BussinessException;
import cn.hqc.basic.utils.GlobalErrorCode;
import cn.hqc.basic.utils.StrUtils;
import cn.hqc.basic.utils.VerifyCodeUtils;
import cn.hqc.user.domain.User;
import cn.hqc.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements VerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String imageCode(String imageCodeKey) throws IOException {
        // 生成一个四位数的验证码
        String imageCode = StrUtils.getRandomString(1);
        // 将验证码存到redis中
        redisTemplate.opsForValue().set(imageCodeKey, imageCode, 5, TimeUnit.MINUTES);
        // 将验证码转成 base64 返回到前端
        return VerifyCodeUtils.VerifyCode(100, 30, imageCode);
    }

    /**
     * 获取手机验证码
     *
     * @param dto
     */
    @Override
    public void smsCode(SmsCodeDto dto) {
        if ("binder".equals(dto.getType())) {
            sendSms(dto, PhoneRegisterCons.BINDER_SMS_CODE_REDIS_KEY);
        } else if ("register".equals(dto.getType())) {
            if (StringUtils.isBlank(dto.getImageCodeKey()) || StringUtils.isBlank(dto.getImageCodeValue())) {
                throw new BussinessException(GlobalErrorCode.PARAM_ERROR);
            }
            verify(dto);
            sendSms(dto,PhoneRegisterCons.SMS_CODE_REDIS_KEY);
        }
    }

    private void sendSms(SmsCodeDto dto,String redisKey) {
        // 两次发送手机验证码间隔是否小于1分钟 register:138xxxxxxx
        Long expire = redisTemplate.getExpire(String.format(redisKey, dto.getPhone()));// 获取当前的key在redis中剩余时间
        if (expire >= (PhoneRegisterCons.REDIS_KEY_TIME - 1) * 60) {
            throw new BussinessException(GlobalErrorCode.TIME_INTERVAL_ERROR);
        }
        // 验证我们是否需要重新生成短信验证码 如果当前redis中存在验证码 那么我们就发送原来的 如果redis中没有 那么我们就新生成一个
        String smsCode = (String) redisTemplate.opsForValue().get(String.format(redisKey, dto.getPhone()));
        if (StringUtils.isBlank(smsCode)) {
            smsCode = StrUtils.getRandomString(4);
        }
        // 将短信验证码保存到redis
        redisTemplate.opsForValue().set(String.format(redisKey, dto.getPhone()), smsCode, PhoneRegisterCons.REDIS_KEY_TIME, TimeUnit.MINUTES);
        // 给客户发送验证码
        log.info("手机验证码为：{}", smsCode);
    }

    private void verify(SmsCodeDto dto) {
        // 校验参数
        // 图形验证码是否正确
        String redisImageCode = (String) redisTemplate.opsForValue().get(dto.getImageCodeKey());
        if (StringUtils.isBlank(redisImageCode) || !dto.getImageCodeValue().equalsIgnoreCase(redisImageCode)) {
            throw new BussinessException(GlobalErrorCode.IMAGE_CODE_ERROR);
        }
        // 手机号是否注册过
        // 根据手机号去查询 user 如果有数据 则说明注册过 要抛异常
        User user = userMapper.findByPhone(dto.getPhone());
        if (null != user) {
            throw new BussinessException(GlobalErrorCode.USER_HAS_REGISTER);
        }
    }
}
